home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / linuxdoc-sgml-1.1 / sgmls-1.1 / lineout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  13.8 KB  |  654 lines

  1. /* lineout.c -
  2.    Implements line-oriented output format.
  3.  
  4.      Written by James Clark (jjc@jclark.com).
  5. */
  6.  
  7. #include "config.h"
  8. #include "std.h"
  9. #include "entity.h"           /* Templates for entity control blocks. */
  10. #include "adl.h"              /* Definitions for attribute list processing. */
  11. #include "sgmlmain.h"         /* Main interface to SGML services. */
  12. #include "lineout.h"
  13. #include "appl.h"
  14.  
  15. static VOID flush_data P((void));
  16. static VOID define_external_entity P((PNE));
  17. static VOID define_entity P((UNCH *));
  18. static VOID handle_attributes P((UNCH *, struct ad *));
  19. static VOID handle_token_list P((UNCH *, struct ad *, int));
  20. static VOID handle_single_token P((UNCH *, struct ad *, int));
  21. static VOID output_notation P((UNCH *, UNCH *, UNCH *));
  22. static VOID output_internal_entity P((UNCH *, int, UNCH *));
  23. static VOID output_external_entity P((UNCH *, int, UNIV, UNCH *, UNCH *,
  24.                       UNCH *));
  25. static VOID output_subdoc P((UNCH *, UNIV, UNCH *, UNCH *));
  26. #ifdef SUPPORT_SUBDOC
  27. static VOID process_subdoc P((UNCH *, UNIV));
  28. #endif /* SUPPORT_SUBDOC */
  29. static VOID output_record_end P((void));
  30. static VOID output_pcdata P((UNS, UNCH *));
  31. static VOID output_cdata P((UNS, UNCH *));
  32. static VOID output_sdata P((UNS, UNCH *));
  33. static VOID output_entity_reference P((UNCH *));
  34. static VOID output_start_tag P((UNCH *));
  35. static VOID output_end_tag P((UNCH *));
  36. static VOID output_processing_instruction P((UNS, UNCH *));
  37. static VOID output_implied_attribute P((UNCH *, UNCH *));
  38. static char *attribute_type_string P((int));
  39. static VOID output_begin_attribute P((UNCH *, UNCH *, int));
  40. static VOID output_attribute_token P((UNS, UNCH *));
  41. static VOID output_end_attribute P((void));
  42. static VOID print_data P((UNS, UNCH *, int));
  43. static VOID print_string P((UNS, UNCH *, int));
  44. static VOID print_id P((UNIV, UNCH *, UNCH *));
  45. static VOID print_filename P((char *));
  46. static VOID output_location P((void));
  47. static VOID output_appinfo P((UNS, UNCH *));
  48.  
  49. static int have_data = 0;
  50. static char *current_filename = 0;
  51. static unsigned long current_lineno = 0;
  52.  
  53. VOID process_document(subdocsw)
  54. int subdocsw;
  55. {
  56.      enum sgmlevent rc;
  57.      struct rcbtag rcbtag;
  58.      struct rcbdata rcbdaf;
  59.  
  60.      while ((rc = sgmlnext(&rcbdaf, &rcbtag)) != SGMLEOD) {
  61. #ifdef SUPPORT_SUBDOC
  62.       if (rc == SGMLDAF && !CONTERSW(rcbdaf) && NDESW(rcbdaf)
  63.           && NEXTYPE(NEPTR(rcbdaf)) == ESNSUB) {
  64.            if (!suppsw && !sgmlment(NEENAME(NEPTR(rcbdaf))))
  65.             define_external_entity(NEPTR(rcbdaf));
  66.            process_subdoc(NEENAME(NEPTR(rcbdaf)) + 1,
  67.                   NEID(NEPTR(rcbdaf)));
  68.            continue;
  69.       }
  70. #endif /* SUPPORT_SUBDOC */
  71.       if (!suppsw)
  72.            switch (rc) {
  73.            case SGMLDAF:
  74.             if (CONTERSW(rcbdaf))
  75.              break;
  76.             if (CDESW(rcbdaf))
  77.              output_cdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  78.             else if (SDESW(rcbdaf))
  79.              output_sdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  80.             else if (NDESW(rcbdaf)) {
  81.              assert(NEXTYPE(NEPTR(rcbdaf)) != ESNSUB);
  82.              if (!sgmlment(NEENAME(NEPTR(rcbdaf))))
  83.                   define_external_entity(NEPTR(rcbdaf));
  84.              output_entity_reference(NEENAME(NEPTR(rcbdaf)) + 1);
  85.             }
  86.             else
  87.              output_pcdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  88.             break;
  89.            case SGMLSTG:
  90.             if (CONTERSW(rcbtag))
  91.              break;
  92.             if (ALPTR(rcbtag))
  93.              handle_attributes((UNCH *)NULL, ALPTR(rcbtag));
  94.             output_start_tag(CURGI(rcbtag));
  95.             break;
  96.            case SGMLETG:
  97.             if (CONTERSW(rcbtag))
  98.              break;
  99.             output_end_tag(CURGI(rcbtag));
  100.             break;
  101.            case SGMLPIS:
  102.             if (CONTERSW(rcbdaf))
  103.              break;
  104.             output_processing_instruction(PDATALEN(rcbdaf),
  105.                           PDATA(rcbdaf));
  106.             break;
  107.            case SGMLREF:
  108.             if (CONTERSW(rcbdaf))
  109.              break;
  110.             output_record_end();
  111.             break;
  112.            case SGMLAPP:
  113.             if (CONTERSW(rcbdaf))
  114.              break;
  115.             if (!subdocsw)
  116.              output_appinfo(ADATALEN(rcbdaf), ADATA(rcbdaf));
  117.             break;
  118.            default:
  119.             abort();
  120.            }
  121.      }
  122. }
  123.  
  124. /* Output an indication that the document was conforming. */
  125.  
  126. VOID output_conforming()
  127. {
  128.      if (!suppsw)
  129.       printf("%c\n", CONFORMING_CODE);
  130. }
  131.  
  132. static VOID define_external_entity(p)
  133. PNE p;
  134. {
  135.      if (NEXTYPE(p) == ESNSUB)
  136.       output_subdoc(NEENAME(p) + 1, NEID(p), NEPUBID(p), NESYSID(p));
  137.      else {
  138.       if (!NEDCNMARK(p))
  139.            output_notation(NEDCN(p) + 1, NEDCNPUBID(p), NEDCNSYSID(p));
  140.       output_external_entity(NEENAME(p) + 1, NEXTYPE(p), NEID(p),
  141.                  NEPUBID(p), NESYSID(p), NEDCN(p) + 1);
  142.       if (NEAL(p))
  143.            handle_attributes(NEENAME(p) + 1, NEAL(p));
  144.      }
  145. }
  146.  
  147. static VOID define_entity(ename)
  148. UNCH *ename;
  149. {
  150.      int rc;
  151.      PNE np;
  152.      UNCH *tp;
  153.      
  154.      if (sgmlment(ename))        /* already defined it */
  155.       return;
  156.      rc = sgmlgent(ename, &np, &tp);
  157.      switch (rc) {
  158.      case 1:
  159.       define_external_entity(np);
  160.       break;
  161.      case 2:
  162.      case 3:
  163.       output_internal_entity(ename + 1, rc == 3, tp);
  164.       break;
  165.      }
  166. }
  167.  
  168. /* ENT is the name of the entity with which these attributes are associated;
  169. if it's NULL, they're associated with the next start tag. */
  170.  
  171. static VOID handle_attributes(ent, al)
  172. UNCH *ent;
  173. struct ad *al;
  174. {
  175.      int aln;
  176.  
  177.      for (aln = 1; aln <= ADN(al); aln++) {
  178.       if (GET(ADFLAGS(al, aln), AERROR))
  179.            ;
  180.       else if (GET(ADFLAGS(al, aln), AINVALID))
  181.            ;
  182.       else if (ADVAL(al, aln) == NULL)
  183.            output_implied_attribute(ent, ADNAME(al, aln));
  184.       else if (ADTYPE(al, aln) >= ATKNLIST)
  185.            handle_token_list(ent, al, aln);
  186.       else
  187.            handle_single_token(ent, al, aln);
  188.       if (BITON(ADFLAGS(al, aln), AGROUP))
  189.            aln += ADNUM(al, aln);
  190.      }
  191. }
  192.  
  193. static VOID handle_token_list(ent, al, aln)
  194. UNCH *ent;
  195. struct ad *al;
  196. int aln;
  197. {
  198.      UNCH *ptr;
  199.      int i;
  200.      if (ADTYPE(al, aln) == AENTITYS) {
  201.       ptr = ADVAL(al, aln);
  202.       for (i = 0; i < ADNUM(al, aln); i++) {
  203.            /* Temporarily make token look like normal
  204.           name with length and EOS. */
  205.            UNCH c = ptr[*ptr + 1];
  206.            ptr[*ptr + 1] = '\0';
  207.            *ptr += 2;
  208.            define_entity(ptr);
  209.            *ptr -= 2;
  210.            ptr += *ptr + 1;
  211.            *ptr = c;
  212.       }
  213.      }
  214.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  215.      ptr = ADVAL(al, aln);
  216.      for (i = 0; i < ADNUM(al, aln); i++) {
  217.       /* The first byte is a length NOT including the length
  218.          byte; the tokens are not EOS terminated. */
  219.       output_attribute_token(*ptr, ptr + 1);
  220.       ptr += *ptr + 1;
  221.      }
  222.      output_end_attribute();
  223. }
  224.  
  225. static VOID handle_single_token(ent, al, aln)
  226. UNCH *ent;
  227. struct ad *al;
  228. int aln;
  229. {
  230.      if (ADTYPE(al, aln) == ANOTEGRP && !DCNMARK(ADDATA(al, aln).x))
  231.       output_notation(ADVAL(al, aln) + 1,
  232.               ADDATA(al, aln).x->pubid,
  233.               ADDATA(al, aln).x->sysid);
  234.      else if (ADTYPE(al, aln) == AENTITY)
  235.       define_entity(ADVAL(al, aln));
  236.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  237.      if (ADTYPE(al, aln) == ACHARS)
  238.       output_attribute_token(ustrlen(ADVAL(al, aln)), ADVAL(al, aln));
  239.      else
  240.       output_attribute_token(*ADVAL(al, aln) - 2, ADVAL(al, aln) + 1);
  241.      output_end_attribute();
  242. }
  243.  
  244. static VOID output_notation(name, pubid, sysid)
  245. UNCH *name;
  246. UNCH *pubid, *sysid;
  247. {
  248.      flush_data();
  249.      print_id((UNIV)0, pubid, sysid);
  250.      printf("%c%s\n", DEFINE_NOTATION_CODE, name);
  251. }
  252.  
  253. static VOID output_internal_entity(ename, is_sdata, text)
  254. UNCH *ename;
  255. int is_sdata;
  256. UNCH *text;
  257. {
  258.      flush_data();
  259.      printf("%c%s %s ", DEFINE_INTERNAL_ENTITY_CODE, ename,
  260.         is_sdata ? "SDATA" : "CDATA");
  261.      print_string(text ? ustrlen(text) : 0, text, 0);
  262.      putchar('\n');
  263. }
  264.  
  265. static VOID output_subdoc(nm, id, pubid, sysid)
  266. UNCH *nm;
  267. UNIV id;
  268. UNCH *pubid, *sysid;
  269. {
  270.      flush_data();
  271.      print_id(id, pubid, sysid);
  272.      printf("%c%s\n", DEFINE_SUBDOC_ENTITY_CODE, nm);
  273. }
  274.  
  275. #ifdef SUPPORT_SUBDOC
  276.  
  277. static VOID process_subdoc(nm, id)
  278. UNCH *nm;
  279. UNIV id;
  280. {
  281.      if (!suppsw) {
  282.       flush_data();
  283.       output_location();
  284.       printf("%c%s\n", START_SUBDOC_CODE, nm);
  285.       fflush(stdout);
  286.      }
  287.      fflush(stderr);
  288.  
  289.      if (id) {
  290.       char **argv;
  291.       int ret;
  292.  
  293.       argv = make_argv(id);
  294.       ret = run_process(argv);
  295.       if (ret != 0)
  296.            suberr++;
  297.       
  298.       current_filename = 0;
  299.       free(argv);
  300.       if (ret == 0)
  301.            get_subcaps();
  302.      }
  303.      else {
  304.       suberr++;
  305.       appl_error(E_SUBDOC, nm);
  306.      }
  307.  
  308.      if (!suppsw)
  309.       printf("%c%s\n", END_SUBDOC_CODE, nm);
  310. }
  311.  
  312. #endif /* SUPPORT_SUBDOC */
  313.  
  314. static VOID output_external_entity(nm, xtype, id, pubid, sysid, dcn)
  315. UNCH *nm, *dcn;
  316. UNIV id;
  317. UNCH *pubid, *sysid;
  318. int xtype;
  319. {
  320.      char *type;
  321.  
  322.      flush_data();
  323.  
  324.      print_id(id, pubid, sysid);
  325.  
  326.      switch (xtype) {
  327.      case ESNCDATA:
  328.       type = "CDATA";
  329.       break;
  330.      case ESNNDATA:
  331.       type = "NDATA";
  332.       break;
  333.      case ESNSDATA:
  334.       type = "SDATA";
  335.       break;
  336.      default:
  337.       return;
  338.      }
  339.      printf("%c%s %s %s\n", DEFINE_EXTERNAL_ENTITY_CODE, nm, type, dcn);
  340. }
  341.  
  342. static VOID output_record_end()
  343. {
  344.      static UNCH re = RECHAR;
  345.      print_data(1, &re, 0);
  346. }
  347.  
  348. static VOID output_pcdata(n, s)
  349. UNS n;
  350. UNCH *s;
  351. {
  352.      print_data(n, s, 0);
  353. }
  354.  
  355. static VOID output_cdata(n, s)
  356. UNS n;
  357. UNCH *s;
  358. {
  359.      print_data(n, s, 0);
  360. }
  361.  
  362. static VOID output_sdata(n, s)
  363. UNS n;
  364. UNCH *s;
  365. {
  366.      print_data(n, s, 1);
  367. }
  368.  
  369. static VOID output_entity_reference(s)
  370. UNCH *s;
  371. {
  372.      flush_data();
  373.      output_location();
  374.      printf("%c%s\n", REFERENCE_ENTITY_CODE, s);
  375. }
  376.  
  377. static VOID output_start_tag(s)
  378. UNCH *s;
  379. {
  380.      flush_data();
  381.      output_location();
  382.      printf("%c%s\n", START_CODE, s);
  383. }
  384.  
  385. static VOID output_end_tag(s)
  386. UNCH *s;
  387. {
  388.      flush_data();
  389.      printf("%c%s\n", END_CODE, s);
  390. }
  391.  
  392. static VOID output_processing_instruction(n, s)
  393. UNS n;
  394. UNCH *s;
  395. {
  396.      flush_data();
  397.      output_location();
  398.      putchar(PI_CODE);
  399.      print_string(n, s, 0);
  400.      putchar('\n');
  401. }
  402.  
  403. static VOID output_appinfo(n, s)
  404. UNS n;
  405. UNCH *s;
  406. {
  407.      flush_data();
  408.      output_location();
  409.      putchar(APPINFO_CODE);
  410.      print_string(n, s, 0);
  411.      putchar('\n');
  412. }
  413.      
  414.  
  415. static VOID output_implied_attribute(ent, aname)
  416. UNCH *ent, *aname;
  417. {
  418.      flush_data();
  419.      if (ent)
  420.       printf("%c%s %s IMPLIED\n", DATA_ATTRIBUTE_CODE, ent, aname);
  421.      else
  422.       printf("%c%s IMPLIED\n", ATTRIBUTE_CODE, aname);
  423. }
  424.  
  425. static char *attribute_type_string(type)
  426. int type;
  427. {
  428.      switch (type) {
  429.      case ANMTGRP:
  430.      case ANAME:
  431.      case ANMTOKE:
  432.      case ANUTOKE:
  433.      case ANUMBER:
  434.      case ANAMES:
  435.      case ANMTOKES:
  436.      case ANUTOKES:
  437.      case ANUMBERS:
  438.      case AID:
  439.      case AIDREF:
  440.      case AIDREFS:
  441.       return "TOKEN";
  442.      case ANOTEGRP:
  443.       return "NOTATION";
  444.      case ACHARS:
  445.       return "CDATA";
  446.      case AENTITY:
  447.      case AENTITYS:
  448.       return "ENTITY";
  449.      }
  450. #if 0
  451.      fatal("invalid attribute type %d", type);
  452. #endif
  453.      return "INVALID";
  454. }      
  455.  
  456. static VOID output_begin_attribute(ent, aname, type)
  457. UNCH *ent, *aname;
  458. int type;
  459. {
  460.      flush_data();
  461.      if (ent)
  462.       printf("%c%s %s %s", DATA_ATTRIBUTE_CODE, ent, aname,
  463.          attribute_type_string(type));
  464.      else
  465.       printf("%c%s %s", ATTRIBUTE_CODE, aname,
  466.          attribute_type_string(type));
  467.  
  468. }
  469.  
  470. static VOID output_attribute_token(vallen, val)
  471. UNS vallen;
  472. UNCH *val;
  473. {
  474.      putchar(' ');
  475.      print_string(vallen, val, 0);
  476. }
  477.  
  478. static VOID output_end_attribute()
  479. {
  480.      putchar('\n');
  481. }
  482.  
  483. static VOID print_data(n, s, is_sdata)
  484. UNS n;
  485. UNCH *s;
  486. int is_sdata;
  487. {
  488.      if (n > 0 || is_sdata) {
  489.       if (n == 1 && *s == RECHAR)
  490.            current_lineno++;
  491.       else
  492.            output_location();
  493.       if (!have_data)
  494.            putchar(DATA_CODE);
  495.       print_string(n, s, is_sdata);
  496.       have_data = 1;
  497.      }
  498. }
  499.  
  500. static VOID flush_data()
  501. {
  502.      if (have_data) {
  503.       putchar('\n');
  504.       have_data = 0;
  505.      }
  506. }
  507.  
  508. static VOID output_location()
  509. {
  510.      char *filename;
  511.      unsigned long lineno;
  512.      int filename_changed = 0;
  513.  
  514.      if (!locsw)
  515.       return;
  516.      if (!sgmlloc(&lineno, &filename))
  517.       return;
  518.      if (!current_filename || strcmp(filename, current_filename) != 0)
  519.       filename_changed = 1;
  520.      else if (lineno == current_lineno)
  521.       return;
  522.      flush_data();
  523.      printf("%c%lu", LOCATION_CODE, lineno);
  524.      current_lineno = lineno;
  525.      if (filename_changed) {
  526.       putchar(' ');
  527.       print_filename(filename);
  528.       current_filename = filename;
  529.      }
  530.      putchar('\n');
  531. }
  532.  
  533. static VOID print_string(slen, s, is_sdata)
  534. UNS slen;
  535. UNCH *s;
  536. int is_sdata;
  537. {
  538.      if (is_sdata)
  539.       fputs("\\|", stdout);
  540.      while (slen > 0) {
  541.       UNCH ch = *s++;
  542.       slen--;
  543.       if (ch == DELSDATA) {
  544.            if (is_sdata)
  545.             ;        /* I don't think this should happen */
  546.            else
  547.             fputs("\\|", stdout);
  548.            ;
  549.       }
  550.       else if (ch == DELCDATA)
  551.            ;
  552.       else {
  553.            if (ch == DELNONCH) {
  554.             if (!slen)
  555.              break;
  556.             ch = UNSHIFTNON(*s);
  557.             s++;
  558.             slen--;
  559.            }
  560.            switch (ch) {
  561.            case RECHAR:
  562.             fputs("\\n", stdout);
  563.             break;
  564.            case '\\':
  565.             fputs("\\\\", stdout);
  566.             break;
  567.            default:
  568.             if (ISASCII(ch) && isprint(ch))
  569.              putchar(ch);
  570.             else
  571.              printf("\\%03o", ch);
  572.             break;
  573.            }
  574.       }
  575.      }
  576.      if (is_sdata)
  577.       fputs("\\|", stdout);
  578. }
  579.             
  580.  
  581. static VOID print_id(id, pubid, sysid)
  582. UNIV id;
  583. UNCH *pubid;
  584. UNCH *sysid;
  585. {
  586.  
  587.      if (pubid) {
  588.       putchar(PUBID_CODE);
  589.       print_string(ustrlen(pubid), pubid, 0);
  590.       putchar('\n');
  591.      }
  592.  
  593.      if (sysid) {
  594.       putchar(SYSID_CODE);
  595.       print_string(ustrlen(sysid), sysid, 0);
  596.       putchar('\n');
  597.      }
  598.  
  599.      if (id) {
  600.       char *p;
  601.  
  602.       for (p = id; *p != '\0'; p++) {
  603.            putchar(FILE_CODE);
  604.            do {
  605.             switch (*p) {
  606.             case '\\':
  607.              fputs("\\\\", stdout);
  608.              break;
  609.             case '\n':
  610.              fputs("\\n", stdout);
  611.              break;
  612.             default:
  613.              if (ISASCII(*p) && isprint((UNCH)*p))
  614.                   putchar(*p);
  615.              else
  616.                   printf("\\%03o", (UNCH)*p);
  617.              break;
  618.             }
  619.            } while (*++p);
  620.            putchar('\n');
  621.       }
  622.      }
  623. }
  624.  
  625. static VOID print_filename(s)
  626. char *s;
  627. {
  628.      for (; *s; s++)
  629.       switch (*s) {
  630.       case '\\':
  631.            fputs("\\\\", stdout);
  632.            break;
  633.       case '\n':
  634.            fputs("\\n", stdout);
  635.            break;
  636.       default:
  637.            if (ISASCII(*s) && isprint((UNCH)*s))
  638.             putchar(*s);
  639.            else
  640.             printf("\\%03o", (UNCH)*s);
  641.            break;
  642.       }
  643. }
  644.  
  645. /*
  646. Local Variables:
  647. c-indent-level: 5
  648. c-continued-statement-offset: 5
  649. c-brace-offset: -5
  650. c-argdecl-indent: 0
  651. c-label-offset: -5
  652. End:
  653. */
  654.